// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

export default class qrj_math {

    /*******************************************************
     *          算法类
     *******************************************************/
    /**
     *      格式化 大数字 (kmgt)
     */
    public static format_big_num(num: number): string {
        let r = 0;

        if (num > 1000000000000000000000000) {  // E
            r = num / 1000000000000000000000000;
            return Math.floor(r * 100) / 100 + "E"  // 输出结果为 15.77
        } else
            if (num > 1000000000000000000000) {  // D
                r = num / 1000000000000000000000;
                return Math.floor(r * 100) / 100 + "D"  // 输出结果为 15.77
            } else
                if (num > 1000000000000000000) {  // C
                    r = num / 1000000000000000000;
                    return Math.floor(r * 100) / 100 + "C"  // 输出结果为 15.77
                } else
                    if (num > 1000000000000000) {  // A
                        r = num / 1000000000000000;
                        return Math.floor(r * 100) / 100 + "A"  // 输出结果为 15.77
                    } else
                        if (num > 1000000000000) {  // T
                            r = num / 1000000000000;
                            return Math.floor(r * 100) / 100 + "T"  // 输出结果为 15.77
                        } else if (num > 1000000000) { // G
                            r = num / 1000000000;
                            return Math.floor(r * 100) / 100 + "B"  // 输出结果为 15.77
                        } else if (num > 1000000) { // M
                            r = num / 1000000;
                            return Math.floor(r * 100) / 100 + "M"  // 输出结果为 15.77
                        } else if (num > 1000) { //K
                            r = num / 1000;
                            return Math.floor(r * 100) / 100 + "K"  // 输出结果为 15.77
                        } else {
                            return "" + num;
                        }
    }


    /**
     *      随机 数
     */
    public static random(min: number, max: number): number {
        return Math.floor(Math.random() * (max - min)) + min;
    }

    /**
     *      上下 误差 随机  wucha = 小数
     */
    public static random_2(v: number, wucha: number): number {
        let min = v - v * wucha;
        let max = v + v * wucha;
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    /**
     *      数组中 随机 去出一个
     */
    public static random_array = function (arr: any[]): any {
        if (arr == null || arr.length == null) {
            cc.error("qrjTools.random_array() 出错!  参数非数组");
            return;
        }
        if (arr.length == 0) {
            return null;
        }
        if (arr.length == 1) {
            return arr[0];
        }
        let t = Math.floor(Math.random() * arr.length);
        return arr[t];
    }

    /**
     *     将  X,Y表示的 移动速度, 转换成 角度,距离 的向量
     *     sudu = V2(x,y) 
     *     返回 = V2(角度,距离);
     */
    public static sudu_2_xiangliang(sudu: cc.Vec2): cc.Vec2 {
        let hd = Math.atan2(sudu.y, sudu.x);
        let rx = Math.cos(hd);
        let p = sudu.x / rx;       //斜边长度

        return cc.v2(this.radian_2_angle(hd), p);
    }

    /**
     *     将  X,Y表示的 移动速度, 转换成 角度,距离 的向量
     *     xiangliang = V2(角度,距离);
     *     返回 = V2(x,y)
     */
    public static xiangliang_2_sudu(xiangliang: cc.Vec2): cc.Vec2 {
        let hd = this.angle_2_radian(xiangliang.x);
        let r = cc.v2();
        r.x = xiangliang.y * Math.cos(hd);
        r.y = xiangliang.y * Math.sin(hd);
        return r;
    }

    /**
     *      弧度 转换 角度
     */
    public static radian_2_angle(radian: number): number {
        var ret = radian * 180 / Math.PI; //弧度转角度，方便调试
        if (ret > 360) {
            ret -= 360;
        }
        if (ret < 0) {
            ret += 360;
        }
        return ret;
    }

    /**
     *     角度 转换 弧度
     */
    public static angle_2_radian(angle: number): number {
        return angle * Math.PI / 180;
    }

    /** 
     *      计算 两个点 形成的 角度
     */
    public static get_angle_2_position(v1: cc.Vec2 | cc.Vec3, v2: cc.Vec2 | cc.Vec3) {
        let v = cc.v2(v2.x - v1.x, v2.y - v1.y);
        let r = Math.atan2(v.y, v.x);
        return this.radian_2_angle(r);
    }

    /**
     *      计算  两点间距离
     */
    public static get_space_2_position(v1: cc.Vec2 | cc.Vec3, v2: cc.Vec2 | cc.Vec3): number {
        // let v = cc.v2(v2.x - v1.x, v2.y - v1.y);
        // let r = Math.sqrt(v.x * v.x + v.y * v.y);
        // return Math.abs(r);

        return cc.v2(v2.x - v1.x, v2.y - v1.y).mag();
    }

    /**
     *     计算 角度差 (<=180度)
     */
    public static get_angle_cha(a: number, b: number): number {
        let t = (a - b) % 360;
        if (Math.abs(t) >= 180) {
            if (t >= 0) {
                return t - 360;
            } else {
                return 360 + t;
            }
        } else {
            return t;
        }
    }

    /**
     *      计算 ab 线段 , 与 cd 线段 是否相交, 以及相交的 焦点
     * @param a  
     * @param b 
     * @param c 
     * @param d 
     */
    public static segmentsIntr(a: cc.Vec2, b: cc.Vec2, c: cc.Vec2, d: cc.Vec2): cc.Vec2 {
        // 三角形abc 面积的2倍  
        var area_abc = (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
        // 三角形abd 面积的2倍  
        var area_abd = (a.x - d.x) * (b.y - d.y) - (a.y - d.y) * (b.x - d.x);
        // 面积符号相同则两点在线段同侧,不相交 (对点在线段上的情况,本例当作不相交处理);  
        if (area_abc * area_abd >= 0) {
            return null;
        }
        // 三角形cda 面积的2倍  
        var area_cda = (c.x - a.x) * (d.y - a.y) - (c.y - a.y) * (d.x - a.x);
        // 三角形cdb 面积的2倍  
        // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出.  
        var area_cdb = area_cda + area_abc - area_abd;
        if (area_cda * area_cdb >= 0) {
            return null;
        }
        //计算交点坐标  
        var t = area_cda / (area_abd - area_abc);
        var dx = t * (b.x - a.x),
            dy = t * (b.y - a.y);
        return cc.v2(a.x + dx, a.y + dy);
    }

    /**
     *     计算  直线 (P1,P2) 与 p3点到直线垂直直线的 交点
     */
    public static get_jiaodian(p1: cc.Vec2, p2: cc.Vec2, p3: cc.Vec2): cc.Vec2 {
        var r = cc.v2();
        //如果p1.x==p2.x 说明是条竖着的线
        if (p1.x - p2.x == 0) {
            r.x = p1.x;
            r.y = p3.y;
        }
        else if (p1.y - p2.y == 0) {
            r.x = p3.x;
            r.y = p1.y;
        }
        else {
            var A = (p1.y - p2.y) / (p1.x - p2.x)
            var B = p1.y - A * p1.x
            var m = p3.x + A * p3.y

            r.x = (m - A * B) / (A * A + 1)
            r.y = A * r.x + B
        }
        return r;
    }

    /**
     *    数组  洗牌
     */
    public static array_xipai(a: any[]) {
        a.sort(function () {
            return Math.random() - 0.5;
        });
    }


    /**
     *   权重随机
     */
    public static qianzhong_random(arr: number[]): number {
        let sum = arr.reduce((a, b) => { return a + b });
        const randomValue = this.random(0, sum);
        let he = 0;
        return arr.findIndex((item) => { he += item; return randomValue <= he });
    }


    /**
     * 数组按某个字段排序
     * @param arr 数组
     * @param field 需要排序的字段
     * @returns 排序后的数组
     */
    public static arraySort(arr: any, field: string, tag: "升序" | "降序") {
        if (tag == "升序") {
            return arr.sort((a: any, b: any) => parseInt(a[field]) - parseInt(b[field]))
        } else {
            return arr.sort((a: any, b: any) => parseInt(b[field]) - parseInt(a[field]))
        }
    }
}
